package git.soulbgm.util;

import git.soulbgm.bean.ConstructorArg;
import git.soulbgm.bean.PropertyArg;

import java.util.ArrayList;

import git.soulbgm.bean.BeanDefinition;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.File;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author 贺瑞杰
 * @version V1.0
 * @date 2018-10-23 14:38
 * @description
 */
public class XmlUtil {

    /**
     * 通过文件的路径获取xml的document对象
     *
     * @param path resources下的地址
     * @return 返回文档对象
     */
    public static Document getXmlByResourcesPath(String path) {
        if (path == null) {
            return null;
        }
        String begin = path.substring(0, 1);
        if (!"/".equals(begin)) {
            path = "/" + path;
        }
        try {
            SAXReader reader = new SAXReader();
            InputStream inputStream = XmlUtil.class.getResourceAsStream(path);
            return reader.read(inputStream);
        } catch (DocumentException e) {
            return null;
        }
    }

    /**
     * 通过File对象获取xml的document对象
     *
     * @param file file对象
     * @return 返回文档对象
     */
    public static Document getXmlByFilePath(File file) {
        if (file == null) {
            return null;
        }
        try {
            SAXReader reader = new SAXReader();
            return reader.read(file);
        } catch (DocumentException e) {
            return null;
        }
    }

    /**
     * 通过xml字符串获取document对象
     *
     * @param xmlStr xml字符串
     * @return 返回文档对象
     */
    public static Document getXmlByString(String xmlStr) {
        if (null == xmlStr || "".equals(xmlStr)) {
            return null;
        }
        try {
            return DocumentHelper.parseText(xmlStr);
        } catch (DocumentException e) {
            return null;
        }
    }

    /**
     * 获取某个节点下的所有子节点
     *
     * @param node 某个节点
     * @return 所有的子子节点
     */
    public static List<Element> getChildElement(Element node) {
        if (node == null) {
            return null;
        }
        return node.elements();
    }

    /**
     * 获取指定的属性值
     *
     * @param node 某个节点
     * @param args 属性名称
     * @return 属性名称和属性值Map
     */
    public static Map<String, String> getAttributes(Element node, String... args) {
        if (node == null || args.length == 0) {
            return null;
        }
        Map<String, String> strMap = new HashMap<>();
        for (String attr : args) {
            strMap.put(attr, node.attributeValue(attr));
        }
        return strMap;
    }


    public static void main(String[] args) {
        Document document = getXmlByResourcesPath("beans.xml");
        List<Element> childElements = getChildElement(document.getRootElement());
        Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>();
        for (Element node : childElements) {
            Map<String, String> map = getAttributes(node, "id", "class");
            BeanDefinition beanDefinition = new BeanDefinition();
            beanDefinition.setBeanName(map.get("id"));
            beanDefinition.setClassPath(map.get("class"));

            List<ConstructorArg> constructorArgs = null;
            List<PropertyArg> propertyArgs = null;

            List<Element> child = getChildElement(node);
            for (Element c : child) {
                if ("constructor-arg".equals(c.getName())) {
                    if (constructorArgs == null) {
                        constructorArgs = new ArrayList<>();
                    }
                    Map<String, String> childMap = getAttributes(c, "index", "name", "ref", "type", "value");
                    ConstructorArg constructorArg = new ConstructorArg();
                    constructorArg.setIndex(childMap.get("index"));
                    constructorArg.setName(childMap.get("name"));
                    constructorArg.setRef(childMap.get("ref"));
                    constructorArg.setType(childMap.get("type"));
                    constructorArg.setValue(childMap.get("value"));
                    constructorArgs.add(constructorArg);
                }
                if ("property".equals(c.getName())) {
                    if (propertyArgs == null) {
                        propertyArgs = new ArrayList<>();
                    }
                    Map<String, String> childMap = getAttributes(c, "name", "ref", "value");
                    PropertyArg propertyArg = new PropertyArg();
                    propertyArg.setName(childMap.get("name"));
                    propertyArg.setRef(childMap.get("ref"));
                    propertyArg.setValue(childMap.get("value"));
                    propertyArgs.add(propertyArg);
                }
            }
            beanDefinition.setConstructorArgs(constructorArgs);
            beanDefinition.setPropertyArgs(propertyArgs);
            beanDefinitionMap.put(map.get("id"), beanDefinition);
        }
        System.out.println(beanDefinitionMap);
    }

}
